package com.yuanian.ecsplus.meta.entity;

import com.github.pagehelper.Page;
import com.yuanian.ecsplus.exception.EcsPlusException;
import com.yuanian.ecsplus.meta.BaseMeta;
import com.yuanian.ecsplus.model.entity.BaseModel;
import com.yuanian.ecsplus.page.Pagination;
import com.yuanian.ecsplus.reflect.PersistenceMetaClass;
import org.springframework.beans.BeanUtils;
import java.util.*;

/**
 * 实体类的元数据
 * @param <T>
 */
public class PersistenceMetaEntity<T extends BaseModel> extends BaseMeta<T> implements MetaEntity<T> {


    public PersistenceMetaEntity(Class<T> clz) {
        super(clz);
    }

    @Override
    public T create(Map initData, T obj) {
        Map data = this.platformSupport.createBoData(getApiName(), initData);
        //补全字段
        this.getMetaClass().copyProperty(obj, data);
        return obj;
    }

    /**
     * 根据dataId查询数据
     *
     * @param dataId
     * @return
     */
    public T selectBoDataByBoDataId(String dataId) {
        Map map = platformSupport.selectBoDataByBoDataId(getApiName(), null, dataId);
        if (map == null) {
            return null;
        }
        this.platformSupport.boMapFullDataConvert(map, getApiName());
        return (T) this.getMetaClass().toEntity(map);
    }

    @Override
    public T selectBoDataByBoMainId(String objectId) {
        Map map = platformSupport.selectBoDataByBoMainId(getApiName(), null, objectId);
        if (map == null) {
            return null;
        }
        this.platformSupport.boMapFullDataConvert(map, getApiName());
        return (T) this.getMetaClass().toEntity(map);
    }

    /**
     * 根据SQL获取数据集合
     * @param sql
     * @return
     */
    public List<T> findList(String sql) {
        List<T> list = new ArrayList<>();
        //获取数据
        List<Map> listMapData = platformSupport.selectBoDataList(getApiName(), null, sql);
        if (listMapData != null) {
            for (Map mapData : listMapData) {
                this.platformSupport.boMapFullDataConvert(mapData, this.getApiName());
                T t = (T) this.getMetaClass().toEntity(mapData);
                list.add(t);
            }
        }
        return list;
    }

    /**
     * 根据SQL获取数据集合,分页显示
     * @param sql
     * @return
     */
    public Pagination<T> findList(String sql, int limit, int offset, boolean totalResults, String orderBy) {
        //获取数据
        List<Map> listMapData = platformSupport.selectBoDataList(getApiName(), null, sql, limit, offset, totalResults, orderBy);
        if (listMapData == null) {
            return null;
        }
        Page page = (Page) listMapData;

        Page result = new Page();
        BeanUtils.copyProperties(page, result);
        result.clear();

        for (Map mapData : listMapData) {
            this.platformSupport.boMapFullDataConvert(mapData, this.getApiName());
            T t = (T) this.getMetaClass().toEntity(mapData);
            result.add(t);
        }
        return new Pagination(result);
    }

    @Override
    public T findFieldList(Map initData, boolean insertFlag) {
        //字段map
        Map map = findFieldListMap(initData, insertFlag);
        return (T) this.getMetaClass().toEntity(map);
    }

    private Map findFieldListMap(Map initData, boolean insertFlag) {
        String apiName = getApiName();
        Map map = this.platformSupport.createBoData(apiName, initData);
        if (map == null) {
            return null;
        }
        if (insertFlag) {
            this.platformSupport.insertBoData(apiName,null, map);
        }
        //Map
        this.platformSupport.boMapFullDataConvert(map, apiName);
        return map;
    }

    public int batchInsert(List<T> obj) {
        List<Map> list = new ArrayList<>();
        //实体和map的对应
        Map<T, Map> objMap = new HashMap();
        for (T t : obj) {
            Map m = this.getMetaClass().toMap(t);
            list.add(m);
            objMap.put(t, m);
        }
        int num = platformSupport.batchInsertBoData(getApiName(), null, list);
        //反写
        Set<Map.Entry<T, Map>> set = objMap.entrySet();
        for (Map.Entry<T, Map> e : set) {
            //得到实体
            //反写
            this.getMetaClass().copyProperty(e.getKey(), e.getValue());
        }
        return num;
    }

    /**
     * 获取实体类的objectId
     * @param obj
     * @return
     */
    public String getObjectId(T obj) {
        try {
            Object id = this.getMetaClass().getIdField().getField().get(obj);
            if (id == null) {
                return null;
            }
            if (id instanceof String) {
                return (String) id;
            }
            return null;
        } catch (IllegalAccessException e) {
            throw new EcsPlusException(e.getCause());
        }
    }

    public PersistenceMetaClass<T> getMetaClass() {
        return this.persistenceMetaClass;
    }

}
